/* eslint-disable camelcase */
import React, { useState, useEffect } from 'react';
import EditModal from './edit-modal';
import AddModal from './add-ipv6';
import NetworkTestModal from './network-test';
import { Button, Input, Form, Table, Icon, Empty, Tabs, Popover, Popconfirm, message } from 'antd';
import {
  getNetConfig,
  getDNSInfo,
  postDNSInfo,
  getRouteInfo,
  deleteRouteInfo
} from '@api/networkConfig';
const { TabPane } = Tabs;
import './index.less';
const prefixCls = 'network-config';
import { _ } from 'core-js';
import PropTypes from 'prop-types';
import { IP_RE } from '@util/constants';
import { actions as netWorkActions } from '@redux/reducer/net-work';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

function NetworkConfig(props) {
  const { form, getStatusNetworkTest, getStatusNetwork, cert } = props;
  const { getFieldDecorator, setFieldsValue, validateFields } = form;
  const [netWorkTableData, setNetWorkTableData] = useState([]);
  const [netWorkTablelodaing, setnetWorkTablelodaing] = useState(false);
  const [editModalVisible, setEditModalVisible] = useState(false);
  const [addModalVisible, setAddModalVisible] = useState(false);
  const [networkTestModalVisible, setNetworkTestModalVisible] = useState(false);
  const [addRouteModalType, setAddRouteModalType] = useState('ipv4');
  const [selectedRowKeys, setSelectedRowKeys] = useState([]);
  const [selectedRow, setSelectedRow] = useState([]);
  const [editNetwork, seEditNetwork] = useState({});
  const [ipv4TableData, setIpv4Data] = useState([]);
  const [ipv6TableData, setIpv6Data] = useState([]);
  const [ipTablelodaing, setIpTablelodaing] = useState(false);
  const [Ipv4page, setIpv4page] = useState({ page: 1, pageSize: 10 });
  const [Ipv6page, setIpv6page] = useState({ page: 1, pageSize: 10 });
  const [Ipv4Count, setIpv4Count] = useState(0);
  const [Ipv6Count, setIpv6Count] = useState(0);
  const [cluster, setCluster] = useState(false);
  // 公共处理返回的是字符串数组方法
  const jsonCallback = (data, param) => {
    if (_.get(data, `data.data.${param}`)) {
      let list = _.get(data, `data.data.${param}`);
      return JSON.parse(list).map((r, index) => {
        r.index = index;
        return r;
      });
    }
    return [];
  };

  // 网络配置列表
  const getNetConfigApi = async () => {
    setnetWorkTablelodaing(true);
    const result = await getNetConfig();
    setnetWorkTablelodaing(false);
    if (_.get(result, 'data.data')) {
      let jsonDate = jsonCallback(result, 'message');
      let { modules, isMaster } = cert;
      // 管理节点的网络配置下不展示扫描口的信息
      if (
        _.includes(modules, 'distribute') &&
        isMaster &&
        jsonDate.find(r => r.name?.includes('work'))
      ) {
        setCluster(true);
        jsonDate = jsonDate.filter(r => !r.name?.includes('scan'));
      }
      setNetWorkTableData(jsonDate);
    }
  };

  // DNS配置
  const DNSInfo = async () => {
    const result = await getDNSInfo();
    if (_.get(result, 'data.data.message')) {
      const message = JSON.parse(_.get(result, 'data.data.message', []));
      const { nameservers } = message;
      if (_.get(nameservers[0], 'length', 0) > 0) {
        let sields = {
          nameserversFirst: nameservers[0],
          nameserversAlternative: nameservers[1]
        };
        setFieldsValue(sields);
      }
    }
  };

  // 路由配置列表
  const getRouteInfoApi = async ({ version = 'ipv4', page = 1, pageSize = 10 }) => {
    setIpTablelodaing(true);
    const result = await getRouteInfo({ version: version, page: page, pageSize: pageSize });
    setIpTablelodaing(false);
    if (_.get(result, 'data.data')) {
      if (version === 'ipv4') {
        setIpv4Data(jsonCallback(result, 'message'));
        setIpv4Count(result.data.data.count);
      } else {
        setIpv6Data(jsonCallback(result, 'message'));
        setIpv6Count(result.data.data.count);
      }
    }
  };
  const isScan = name => {
    if (!name) {
      return;
    }
    let dictName = { mgmt: '管理口' };
    if (dictName[name]) {
      return dictName[name];
    }
    if (name.includes('work')) {
      // eslint-disable-next-line eqeqeq
      return `工作口${name.substring(4) == 0 ? '' : name.substring(4)}`;
    }
    if (name.includes('scan')) {
      // eslint-disable-next-line eqeqeq
      return `扫描口${name.substring(4) == 0 ? '' : name.substring(4)}`;
    }
  };
  useEffect(() => {
    if (Ipv4Count) {
      if (Math.ceil(Ipv4Count / Ipv4page.pageSize) < Ipv4page.page) {
        setIpv4page({ page: Ipv4page.page - 1, pageSize: Ipv4page.pageSize });
      }
    }
  }, [Ipv4Count]);
  useEffect(() => {
    if (Ipv6Count) {
      if (Math.ceil(Ipv6Count / Ipv6page.pageSize) < Ipv6page.page) {
        setIpv6page({ page: Ipv6page.page - 1, pageSize: Ipv6page.pageSize });
      }
    }
  }, [Ipv6Count]);
  // 路由分页切换
  const ipPageChange = ({ current, pageSize }, type) => {
    type === 'ipv4'
      ? setIpv4page({
          page: current,
          pageSize
        })
      : setIpv6page({
          page: current,
          pageSize
        });
  };
  // 新增ip路由
  const AddModalOnOK = type => {
    const page = type === 'ipv4' ? Ipv4page : Ipv6page;
    getRouteInfoApi({ version: type, ...page });
    setAddModalVisible(false);
  };
  //  删除路由Api
  const deleteRoute = async (list, type) => {
    let rebuildList = list.map(r => {
      return { dev: r.name, to: r.to, mask: r.mask, via: r.via };
    });
    try {
      await deleteRouteInfo({ list: rebuildList });
      message.success('删除成功');
      setSelectedRow([]);
      setSelectedRowKeys([]);
      const page = type === 'ipv4' ? Ipv4page : Ipv6page;
      getRouteInfoApi({ version: type, ...page });
    } catch (error) {
      message.error('删除失败');
    }
  };
  // 删除路由方法
  const confirm = (row, type) => {
    if (row) {
      deleteRoute([row], type);
    } else {
      deleteRoute(selectedRowKeys, type);
    }
  };

  useEffect(() => {
    getRouteInfoApi({ ...Ipv4page, version: 'ipv4' });
  }, [Ipv4page]);

  useEffect(() => {
    getRouteInfoApi({ ...Ipv6page, version: 'ipv6' });
  }, [Ipv6page]);

  useEffect(() => {
    getNetConfigApi();
    DNSInfo();
  }, []);

  const editNetworkConfig = row => {
    seEditNetwork(row);
    setEditModalVisible(true);
  };
  const addIP = type => {
    setAddRouteModalType(type);
    setAddModalVisible(true);
  };
  const setNetworkTest = () => {
    setNetworkTestModalVisible(true);
  };
  const editModalOnOk = () => {
    setEditModalVisible(false);
    getNetConfigApi();
  };

  const getPortNetworkColumns = () => {
    const columns = [
      {
        title: '网口名称',
        className: 'rawname',
        dataIndex: 'rawname'
      },
      {
        title: (
          <div>
            网口用途
            <Popover
              overlayStyle={{ width: 390 }}
              content={
                <div>
                  <p>
                    1、管理口：设备正常情况下该网口无需接入网线。如果需要对设备进行管理时，可将该网口接入网线，网线另一端连接到笔记本，将笔记本配置成与管理口同一局域网，即可在笔记本上通过浏览器访问管理口IP，进入到系统。
                  </p>
                  <p>
                    2、工作口：设备正常工作的网口，也是任务扫描的默认网口。需要将工作口接入网线，另一端接入交换机，并配置好网口信息，才能正常工作。
                  </p>
                  <p>
                    3、扫描口：可用于任务扫描。如果工作口作为扫描口不够用或者扫描口与工作口分开使用，可以设置扫描口。需要将扫描口接入网线，另一端接入交换机，并配置好网口信息，才能正常工作。
                  </p>
                </div>
              }
            >
              <Icon type="info-circle" style={{ marginLeft: 4, color: '#999EA8' }} />
            </Popover>
          </div>
        ),
        className: 'name',
        dataIndex: 'name',
        render: row => {
          return <>{isScan(row)}</>;
        }
      },
      {
        title: 'IPv4地址',
        className: 'address_ipv4',
        dataIndex: 'address_ipv4'
      },
      {
        title: 'IPv4子网掩码',
        className: 'netmask_ipv4',
        dataIndex: 'netmask_ipv4'
      },
      {
        title: 'IPv4网关',
        dataIndex: 'gateway4',
        render: (row, rows) => {
          if (!rows.name.includes('work')) {
            return <>-</>;
          }
          return <>{row}</>;
        }
      },
      {
        title: 'IPv6地址',
        className: 'address_ipv6',
        dataIndex: 'address_ipv6'
      },
      {
        title: 'IPv6前缀长度',
        className: 'netmask_ipv6',
        dataIndex: 'netmask_ipv6'
      },
      {
        title: 'IPv6网关',
        className: 'gateway6',
        dataIndex: 'gateway6',
        render: (row, rows) => {
          if (!rows.name.includes('work')) {
            return <>-</>;
          }
          return <>{row}</>;
        }
      },
      {
        title: '操作',
        className: 'user-operate',
        key: 'operator',
        width: 100,
        render: row => {
          let dict = { work: '工作口', mgmt: '管理口', scan0: '扫描口' };
          return (
            <Button
              type="link"
              disabled={row.name === 'mgmt' || (row.name.includes('work') && cluster)}
              onClick={() => editNetworkConfig({ ...row, cnName: dict[row.name] })}
            >
              编辑
            </Button>
          );
        }
      }
    ];
    return columns;
  };

  const getIpcolumns = type => {
    const ip4Columns = [
      {
        title: '网络地址',
        className: 'to',
        dataIndex: 'to'
      },
      {
        title: '子网掩码',
        className: 'mask',
        dataIndex: 'mask'
      },
      {
        title: '路由节点',
        className: 'via',
        dataIndex: 'via'
      },
      {
        title: '网口名称',
        className: 'rawname',
        dataIndex: 'rawname'
      },
      {
        title: '网口用途',
        className: 'name',
        dataIndex: 'name',
        render: row => {
          return <>{isScan(row)}</>;
        }
      },
      {
        title: '操作',
        className: 'user-operate',
        key: 'operator',
        width: 100,
        render: row => {
          return (
            <Popconfirm
              title="确定删除吗?"
              okText="确定"
              cancelText="取消"
              onConfirm={() => confirm(row, type)}
            >
              <Button type="link">删除</Button>
            </Popconfirm>
          );
        }
      }
    ];
    const ip6Columns = [
      {
        title: '网络地址',
        className: 'to',
        dataIndex: 'to'
      },
      {
        title: '前缀长度',
        className: 'mask',
        dataIndex: 'mask'
      },
      {
        title: '路由节点',
        className: 'via',
        dataIndex: 'via'
      },
      {
        title: '网口名称',
        className: 'rawname',
        dataIndex: 'rawname'
      },
      {
        title: '网口用途',
        className: 'name',
        dataIndex: 'name',
        render: row => {
          return <>{isScan(row)}</>;
        }
      },
      {
        title: '操作',
        className: 'user-operate',
        key: 'operator',
        width: 100,
        render: row => {
          return (
            <Popconfirm
              title="确定删除吗?"
              okText="确定"
              cancelText="取消"
              onConfirm={() => confirm(row, type)}
            >
              <Button type="link">删除</Button>
            </Popconfirm>
          );
        }
      }
    ];
    return { ipv4: ip4Columns, ipv6: ip6Columns }[type];
  };

  const portNetworkColumns = getPortNetworkColumns();

  const rowSelection = {
    selectedRowKeys: selectedRow,
    onChange: (selectedRowKeys, rows) => {
      setSelectedRow(selectedRowKeys);
      setSelectedRowKeys(rows);
    }
  };

  const DSNetworkTest = () => {
    let sum = [false, false];
    netWorkTableData.map(value => {
      if (value.name.includes('work')) {
        sum[0] = true;
      }
      if (value.name.includes('scan0')) {
        sum[1] = true;
      }
      return sum;
    });
    return sum.every(r => !r);
  };
  const PortConfig = () => {
    return (
      <>
        <div className={`${prefixCls}-page-title`}>
          网口配置
          <Button
            type="primary"
            className="float-right"
            onClick={() => setNetworkTest()}
            disabled={DSNetworkTest()}
          >
            网络连通性测试
          </Button>
        </div>
        <div>当前共“{_.get(netWorkTableData, 'length', 0)}”个网口</div>
        <Table
          rowKey="_id"
          dataSource={netWorkTableData}
          pagination={false}
          columns={portNetworkColumns}
          loading={{ spinning: netWorkTablelodaing, tip: '加载中' }}
          locale={{
            emptyText: (
              <Empty
                description={netWorkTableData.length === 0 ? ' ' : '暂无数据'}
                image={Empty.PRESENTED_IMAGE_SIMPLE}
              />
            )
          }}
          className="user-table"
        />
      </>
    );
  };

  const DnsConfig = () => {
    // 保存dns配置
    const onOk = () => {
      validateFields(async (err, values) => {
        if (!err) {
          try {
            let dns = [values.nameserversFirst];
            if (values.nameserversAlternative) {
              dns.push(values.nameserversAlternative);
            }
            await postDNSInfo({ dns: dns });
            message.success('更改成功');
            DNSInfo();
            await getStatusNetworkTest();
            getStatusNetwork();
          } catch (error) {
            message.error(_.get(error, 'error.response.data.error') || '更改失败');
            return;
          }
        }
      });
    };
    const formItemLayout = {
      labelCol: {
        span: 4
      },
      wrapperCol: {
        span: 20
      }
    };
    return (
      <>
        <div className={`${prefixCls}-page-title mt20`}>DNS配置</div>
        <div className={`${prefixCls}-form`}>
          <Form labelAlign="left">
            <Form.Item {...formItemLayout} label="首选DNS" colon={false}>
              {getFieldDecorator('nameserversFirst', {
                rules: [
                  {
                    required: true,
                    message: '请输入首选DNS'
                  },
                  {
                    pattern: IP_RE,
                    message: '您输入的格式有误'
                  }
                ],
                validateFirst: true
              })(<Input placeholder="请输入DNS服务器地址" />)}
            </Form.Item>
            <Form.Item {...formItemLayout} label="备选DNS" colon={false}>
              {getFieldDecorator('nameserversAlternative', {
                rules: [
                  {
                    pattern: IP_RE,
                    message: '您输入的格式有误'
                  }
                ]
              })(<Input placeholder="请输入DNS服务器地址" />)}
            </Form.Item>
            <Form.Item {...formItemLayout} label={' '} colon={false}>
              <Button
                type="primary"
                loading={false}
                onClick={onOk}
                className={`${prefixCls}-form-btn button-forwards`}
              >
                保存修改
              </Button>
            </Form.Item>
          </Form>
        </div>
      </>
    );
  };

  const IPConfig = type => {
    const pagination = {
      total: type === 'ipv4' ? Ipv4Count : Ipv6Count,
      current: type === 'ipv4' ? Ipv4page.page : Ipv6page.page,
      pageSize: type === 'ipv4' ? Ipv4page.pageSize : Ipv6page.pageSize,
      showQuickJumper: true,
      showSizeChanger: false,
      showTotal: num => `共 ${num} 条`,
      size: 'small'
    };
    return (
      <>
        <div className="mb20">
          <Popconfirm
            title="确定删除吗?"
            okText="确定"
            cancelText="取消"
            onConfirm={() => confirm(null, type)}
          >
            <Button
              type="danger"
              style={{ marginRight: 16 }}
              disabled={_.get(selectedRowKeys, 'length', 0) === 0}
            >
              删除
            </Button>
          </Popconfirm>
          <Button type="primary" className="float-right" onClick={() => addIP(type)}>
            {type === 'ipv4' ? '添加IPv4路由' : '添加IPv6路由'}
          </Button>
        </div>
        <Table
          rowKey={record => record.index}
          dataSource={type === 'ipv4' ? ipv4TableData : ipv6TableData}
          columns={getIpcolumns(type)}
          loading={{ spinning: ipTablelodaing, tip: '加载中' }}
          rowSelection={rowSelection}
          pagination={pagination}
          onChange={e => {
            ipPageChange(e, type);
          }}
          locale={{
            emptyText: (
              <Empty
                description={
                  (type === 'ipv4' ? ipv4TableData : ipv6TableData).length !== 0 ? ' ' : '暂无数据'
                }
                image={Empty.PRESENTED_IMAGE_SIMPLE}
              />
            )
          }}
          className="user-table"
        />
      </>
    );
  };

  return (
    <>
      <div className={prefixCls}>
        {PortConfig()}
        {DnsConfig()}
        {!cluster && (
          <>
            <div className={`${prefixCls}-page-title`}>路由表配置</div>
            <Tabs
              defaultActiveKey="1"
              onChange={() => {
                setSelectedRow([]), setSelectedRowKeys([]);
              }}
            >
              <TabPane tab="IPv4路由表" key="1">
                {IPConfig('ipv4')}
              </TabPane>
              <TabPane tab="IPv6路由表" key="2">
                {IPConfig('ipv6')}
              </TabPane>
            </Tabs>
          </>
        )}
      </div>
      <EditModal
        visible={editModalVisible}
        onOk={() => editModalOnOk()}
        onCancel={() => setEditModalVisible(false)}
        data={editNetwork}
      />
      <AddModal
        visible={addModalVisible}
        modalType={addRouteModalType}
        onOk={e => AddModalOnOK(e)}
        onCancel={() => setAddModalVisible(false)}
        netWorkTableData={netWorkTableData}
      />
      <NetworkTestModal
        visible={networkTestModalVisible}
        onCancel={() => setNetworkTestModalVisible(false)}
        okText="重新检测"
        cancelText="关闭"
        filterSacn={cluster}
      />
    </>
  );
}

NetworkConfig.propTypes = {
  form: PropTypes,
  getStatusNetworkTest: PropTypes.func,
  getStatusNetwork: PropTypes.func,
  messageList: PropTypes.array,
  cert: PropTypes.object
};

const mapStateToProps = state => {
  return {
    messageList: _.get(state, 'netWork.messageList', {}),
    cert: _.get(state, 'auth.cert', {})
  };
};

const mapDispatchToProps = dispatch => {
  return {
    ...bindActionCreators(netWorkActions, dispatch)
  };
};
export default Form.create()(
  connect(
    mapStateToProps,
    mapDispatchToProps
  )(NetworkConfig)
);
